前一天我們了解了管理者功能的入口登入功能,今天我們要繼續進入到管理者的主畫面-ManagerActivity.kt,在畫面中,我們會看到三個按鈕分別是-課表內容編輯、教室細項設定、所有教室狀態;雖然我們今天不會探究這三項功能裡面的內容,但作為一個 App 的選單入口,也是必不可少的功能。
一開始設計這頁面時,我們組內就討論出可能會有三個選項來提供給管理者設定。
不過當中,其實遇到了一個問題,就是我們事先設計好管理者頁面,才在之後接上登入功能;這樣的作法上看起來沒有錯,但其中一個核心的邏輯問題我們卻忽視了:那就是進入頁面時沒有檢查 isLoggedIn 。這個重大疏忽可能造就了如果有某個地方可以啟動 ManagerActivity,代表其他地方可以繞過登入檢查。

ManagerActivity.kt 負責什麼和 Hermes Agent 一起重讀課表管理頁面後,ManagerActivity.kt 是管理者登入成功後看到的主畫面。它負責管理者後台的選單頁,提供不同按鈕讓使用者跳到不同功能頁:課表管理、教室詳細設定、瀏覽教室狀態、離開/登出。
主要的邏輯有以下四點:
val lessonSettingButton = findViewById<Button>(R.id.lesson_setting)
lessonSettingButton.setOnClickListener {
val intent = Intent(this, LessonManageActivity::class.java)
startActivity(intent)
}
LessonManageActivity。後面可以追這個頁面是否負責新增或修改課表資料。val classroomSettingButton = findViewById<Button>(R.id.classroom_setting)
classroomSettingButton.setOnClickListener {
val intent = Intent(this, ClassroomChooseManageActivity::class.java)
startActivity(intent)
}
ClassroomChooseManageActivity。這條線可以修改教室的類型。val browseClassroomsButton = findViewById<Button>(R.id.browse_classrooms_button)
browseClassroomsButton.setOnClickListener {
val intent = Intent(this, AllClassroomsActivity::class.java)
startActivity(intent)
}
AllClassroomsActivity。後面會接到查看所有教室的有課時段以及可以新增教室。val exitButton = findViewById<Button>(R.id.exit_button)
exitButton.setOnClickListener {
val pref = getSharedPreferences("LoginData", Context.MODE_PRIVATE)
pref.edit().putBoolean("isLoggedIn", false).apply()
Toast.makeText(this, "已登出並返回主畫面", Toast.LENGTH_SHORT).show()
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}
isLoggedIn 設成 false,顯示「已登出並返回主畫面」,重新回到乾淨的 MainActivity,避免使用者按返回鍵又回到管理者頁面。 LoginActivity
「登入成功」
│
▼
ManagerActivity
「管理者後台」
│
├──→ 課表內容編輯
│ 「修改課表時段」
│
├──→ 教室細項設定
│ 「修改教室類型」
│
└──→ 所有教室狀態
「查看 / 新增教室」
│
▼
離開後台
│
▼
清除登入狀態
│
▼
MainActivity
ManagerActivity 是 RoomRush 管理者登入成功後的主選單頁。
manager.xml 作為畫面,提供三個主要功能入口:按下「課表內容編輯」會進入 LessonManageActivity。ClassroomChooseManageActivity。AllClassroomsActivity。SharedPreferences 把 isLoggedIn 設為 false,顯示登出提示,並用 FLAG_ACTIVITY_NEW_TASK 與 FLAG_ACTIVITY_CLEAR_TASK 清除 Activity 堆疊後回到 MainActivity。值得注意的是,這個檔案目前沒有在 onCreate() 開頭檢查 isLoggedIn,因此如果有方式直接啟動 ManagerActivity,可能會繞過登入流程。
ManagerActivity 沒有檢查 isLoggedIn,雖然有登出,但沒有在進入時明確驗證登入狀態。這代表如果有某個地方可以啟動 ManagerActivity,可能有其他地方可以繞過登入檢查。
ManagerActivity 在建立時(onCreate)時,完全沒有驗證使用者是否已成功登入(isLoggedIn),這代表只要頁面被開啟就預設放行,缺乏最基本的身分審核。Intent、設定了未妥善保護的 Deep Link 【註1】,甚至透過 ADB(Android Debug Bridge)【註2】 指令直接指定啟動該 Activity,任何人都能跳過登入頁直接進入管理後台。【註1】 Deep Link(深層連結): 允許外部透過自訂 URI(網址)直接啟動 App 內部特定頁面的跳轉技術。
【註2】 ADB(Android Debug Bridge): 官方除錯命令列工具,可透過指令強制跳轉啟動特定 Activity,略過正常的 UI 流程。
讀完 LoginActivity 後,我接著看 ManagerActivity。這個檔案不是直接管理資料,而是管理者登入後的功能選單。它提供三條路徑:課表管理、教室詳細設定,以及瀏覽教室狀態。這讓我可以把管理者功能拆成幾條後續主線,而不是一次混在一起看。
這個檔案也讓我看到一個安全性細節:它有登出機制,按離開時會把 isLoggedIn 改成 false,並清掉頁面堆疊回到主畫面。不過,目前沒有看到它在進入頁面時檢查 isLoggedIn。也就是說,登入流程目前主要靠 LoginActivity 控制,但 ManagerActivity 本身沒有再做一道防線。這可以記成後續改善點。
一句話重點總結 ManagerActivity:
ManagerActivity是登入後的管理者選單頁,負責提供課表管理、教室設定、瀏覽教室狀態的入口,並在離開時清除登入狀態回到主頁。
大致上了解管理者主頁面後,我們發現其中很嚴重的漏洞,未來如果要開發成真的 App 時,也要注意這些小細節。
接下來我們會進入到第一個管理者功能——「課表內容編輯」,我們會讀 LessonManageActivity.kt 以及 LessonManageViewModel.kt ,理解課表管理頁如何選條件及修改「是/否」有課及刪除既有的教室,並把修改和刪除的資料庫內容交給 Repository。